package com.linkhub.oms.admin.modules.shop.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.excel.util.StringUtils;
import com.google.common.collect.Lists;
import com.linkhub.oms.admin.common.exception.ExceptionFactory;
import com.linkhub.oms.admin.common.util.I18nMessageUtil;
import com.linkhub.oms.admin.modules.satoken.session.LhSessionContext;
import com.linkhub.oms.admin.modules.shop.domain.param.*;
import com.linkhub.oms.admin.modules.shop.domain.vo.AddShopVO;
import com.linkhub.oms.admin.modules.shop.domain.vo.AddShopVOV2;
import com.linkhub.oms.admin.modules.shop.domain.vo.ShopVO;
import com.linkhub.oms.admin.modules.shop.service.ShopBizService;
import com.linkhub.oms.common.constant.QtRegexPool;
import com.linkhub.oms.common.constant.SaTokenConstant;
import com.linkhub.oms.common.constant.ShopifyConstant;
import com.linkhub.oms.common.enums.IEnumConvert;
import com.linkhub.oms.common.enums.mp.DataStatusEnum;
import com.linkhub.oms.common.enums.mp.PlatFormEnum;
import com.linkhub.oms.common.enums.mp.SuccessfulEnum;
import com.linkhub.oms.common.exception.BizException;
import com.linkhub.oms.common.util.QtStreamUtil;
import com.linkhub.oms.component.transactional.service.TransactionalCallBackService;
import com.linkhub.oms.dao.mpservice.IShopService;
import com.linkhub.oms.dao.mpservice.ITemporaryCodeService;
import com.linkhub.oms.data.sync.api.shopify.domain.response.OauthAccessTokenResponse;
import com.linkhub.oms.data.sync.api.shopify.domain.response.ShopAccessScopesResponse;
import com.linkhub.oms.data.sync.api.shopify.domain.response.ShopResponse;
import com.linkhub.oms.data.sync.service.ShopifyApiService;
import com.linkhub.oms.entity.ShopEntity;
import com.linkhub.oms.entity.TemporaryCodeEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Description: ShopBizService
 * @Author: echo
 * @Date: 2024/3/20 21:14
 * @Version: 1.0
 */
@Slf4j
@Service
public class ShopBizServiceImpl implements ShopBizService {

    @Resource
    private IShopService shopService;
    @Resource
    private ShopifyApiService shopifyApiService;
    @Resource
    private TransactionalCallBackService transactionalCallBackService;
    @Resource
    private ITemporaryCodeService temporaryCodeService;

    @Override
    public List<ShopVO> listShops(ShopQueryParam shopQueryParam) {
        // 查询当前用户所有商店
        SuccessfulEnum successfulEnum = getSuccessfulEnum(shopQueryParam);
        List<ShopEntity> shops = shopService.listByUserId(shopQueryParam.getUserId(), successfulEnum);
        if (CollUtil.isEmpty(shops)) {
            return Lists.newArrayList();
        }

        return QtStreamUtil.map(shops, ShopVO::convert);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AddShopVO saveShop(AddShopParam addShopParam) {
        String userId = addShopParam.getUserId();
        String shopName = addShopParam.getShopName();
        String url = addShopParam.getUrl();
        Integer platForm = addShopParam.getPlatForm();

        ShopEntity preShopInfo = createPreShopInfo(addShopParam);

        // URL参数校验
        PlatFormEnum platformEnum = IEnumConvert.valueOf(platForm, PlatFormEnum.class);
        if (PlatFormEnum.SHOPIFY.equals(platformEnum)) {
            if (!(url != null && url.length() >= 1 && url.length() <= 200)) {
                throw ExceptionFactory.getI18nBizException("validation.shopUrl.length");
            }
            if (!url.matches(QtRegexPool.SHOPIFY_URL)) {
                throw ExceptionFactory.getI18nBizException("validation.shopUrl.pattern");
            }

            if (shopService.checkShopExist(url)) {
                throw ExceptionFactory.getI18nBizException("shop.url.bind.error");
            }
        } else if (PlatFormEnum.SHIPO.equals(platformEnum)) {
            preShopInfo.setAuthorization(SuccessfulEnum.YES);
            preShopInfo.setAuthorizationTime(LocalDateTime.now());
        }

        boolean shopExist = shopService.checkShopExist(userId, shopName, url);
        if (shopExist) {
            throw ExceptionFactory.getI18nBizException("shop.exist.error");
        }


        shopService.save(preShopInfo);

        // 事务提交后
        transactionalCallBackService.syncHandleAfterCommit(this, service -> {
            LhSessionContext.removeUserSessionKey(userId, SaTokenConstant.CUSTOMER_SHOP_LIST);
        });
        return AddShopVO.builder().sysShopId(preShopInfo.getSysShopId()).build();
    }

    @Override
    @SuppressWarnings("all")
    public void updateShopToken(AuthorizationGrantParam grantParam) {
        String sysShopId = grantParam.getSysShopId();
        ShopEntity userShop = shopService.getUserShop(grantParam.getUserId(), sysShopId);
        if (Objects.isNull(userShop)) {
            throw ExceptionFactory.getI18nBizException("shop.absent.error");
        }
        String shopUrl = userShop.getUrl();
        // 获取accessToken
        OauthAccessTokenResponse shopAccessToken = shopifyApiService.getShopAccessToken(shopUrl, grantParam.getCode());
        String accessToken = shopAccessToken.getAccessToken();
        // 获取商店信息并更新到数据库
        ShopResponse shopInfo = shopifyApiService.getShopInfo(shopUrl, accessToken);
        ShopResponse.Shop shop = shopInfo.getShop();
        userShop.setAccessToken(accessToken);
        userShop.setAuthorization(SuccessfulEnum.YES);
        userShop.setAuthorizationTime(LocalDateTime.now());
        userShop.setShopId(shop.getId());
        ShopResponse.Logo logo = shop.getLogo();
        if(logo != null) {
            userShop.setLogoUrl(logo.getAttachment_blob_url());
        }

        shopService.updateById(userShop);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateShopUnauthorized(String token) {
        shopService.updateShopAuthorizationStatus(token, SuccessfulEnum.NO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateShopName(EditShopParam editShopParam) {
        String sysShopId = editShopParam.getSysShopId();
        boolean shopExist = shopService.checkShopExist(editShopParam.getUserId(),
                editShopParam.getShopName(), Lists.newArrayList(sysShopId));
        if (shopExist) {
            throw ExceptionFactory.getI18nBizException("shop.exist.error");
        }
        ShopEntity update = new ShopEntity();
        update.setShopName(editShopParam.getShopName());
        update.setLogoUrl(editShopParam.getLogoUrl());
        shopService.updateBySysShopId(sysShopId, update);

    }

    @Override
    public AddShopVOV2 saveShopV2( AddShopParamV2 addShopParamV2 ) {
        String temporaryCode = addShopParamV2.getTemporaryCode();
        TemporaryCodeEntity temporaryCodeEntity = temporaryCodeService.getByTemporaryCode(temporaryCode);
        if (temporaryCodeEntity == null) {
            throw ExceptionFactory.getI18nBizException("temporaryCode.not.exist.error");
        }
//        Timestamp createdTime = temporaryCodeEntity.getCreatedTime();
//        LocalDateTime createdAt = createdTime.toLocalDateTime();
//        LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault());
//        if (createdAt.plusHours(SaTokenConstant.TEMPORARY_CODE_EXPIRE_HOURS).isBefore(now)) {
//            throw ExceptionFactory.getI18nBizException("temporaryCode.expire.error");
//        }

        String userId = temporaryCodeEntity.getSourceCode();

        String url = addShopParamV2.getUrl();
        Integer platForm = addShopParamV2.getPlatForm();
        String accessToken = addShopParamV2.getAccessToken();
        String shopName = addShopParamV2.getShopName();
        ShopEntity preShopInfo = createPreShopInfoV2(addShopParamV2, userId);

        PlatFormEnum platformEnum = IEnumConvert.valueOf(platForm, PlatFormEnum.class);
        if (PlatFormEnum.SHOPIFY.equals(platformEnum)) {
            if (StringUtils.isBlank(accessToken) || accessToken.length() > 200 || !accessToken.matches(QtRegexPool.SHOPIFY_ACCESS_TOKEN)) {
                throw ExceptionFactory.getI18nBizException("validation.accessToken.length");
            }
            if (!(url != null && url.length() >= 1 && url.length() <= 200)) {
                throw ExceptionFactory.getI18nBizException("validation.shopUrl.length");
            }
            if (!url.matches(QtRegexPool.SHOPIFY_URL)) {
                throw ExceptionFactory.getI18nBizException("validation.shopUrl.pattern");
            }
            if (shopService.checkShopExist(url)) {
                throw ExceptionFactory.getI18nBizException("shop.url.bind.error");
            }

            // 校验token 权限
            ShopAccessScopesResponse shopAccessScopes = shopifyApiService.getShopAccessScopes(url, accessToken);
            if (!shopAccessScopes.success()) {
                throw new BizException(I18nMessageUtil.getMessage("validation.shopAccessScopes.error", shopAccessScopes.getErrors()));
            }
            // 提取返回的权限列表
            List<String> grantedScopes = shopAccessScopes.getAccessScopes()
                    .stream()
                    .map(ShopAccessScopesResponse.AccessScope::getHandle)
                    .collect(Collectors.toList());
            // 找出 MUST_ACCESS_SCOPES 中未被 grantedScopes 包含的权限
            List<String> missingScopes = ShopifyConstant.MUST_ACCESS_SCOPES.stream()
                    .filter(requiredScope -> !grantedScopes.contains(requiredScope))
                    .collect(Collectors.toList());
            if (!missingScopes.isEmpty()) {
                throw new BizException(I18nMessageUtil.getMessage("validation.shopAccessScopes.miss.error", missingScopes));
            }

            // 获取商店信息
            ShopResponse shopInfo = shopifyApiService.getShopInfo(url, accessToken);
            ShopResponse.Shop shop = shopInfo.getShop();
            preShopInfo.setShopId(shop.getId());
            preShopInfo.setAuthorization(SuccessfulEnum.YES);
            preShopInfo.setAuthorizationTime(LocalDateTime.now());
        } else if (PlatFormEnum.SHIPO.equals(platformEnum)) {
            preShopInfo.setAuthorization(SuccessfulEnum.YES);
            preShopInfo.setAuthorizationTime(LocalDateTime.now());
        }

        boolean shopExist = shopService.checkShopExist(userId, shopName, url);
        if (shopExist) {
            throw ExceptionFactory.getI18nBizException("shop.exist.error");
        }

        shopService.save(preShopInfo);

        // 事务提交后
        transactionalCallBackService.syncHandleAfterCommit(this, service -> {
            LhSessionContext.removeUserSessionKey(userId, SaTokenConstant.CUSTOMER_SHOP_LIST);
        });

        return AddShopVOV2.builder().sysShopId(preShopInfo.getSysShopId()).authorization(SuccessfulEnum.YES).build();
    }


    private SuccessfulEnum getSuccessfulEnum(ShopQueryParam shopQueryParam) {
        return IEnumConvert.valueOf(shopQueryParam.getAuthorization(), SuccessfulEnum.class);
    }

    private ShopEntity createPreShopInfo(AddShopParam addShopParam) {
        String sysShopId = IdUtil.getSnowflake().nextIdStr();
        ShopEntity shopEntity = new ShopEntity();
        shopEntity.setUserId(addShopParam.getUserId());
        shopEntity.setSysShopId(sysShopId);
        shopEntity.setShopId(Long.valueOf(sysShopId));
        shopEntity.setShopName(addShopParam.getShopName());
        shopEntity.setUrl(addShopParam.getUrl());
        shopEntity.setLogoUrl(addShopParam.getLogoUrl());
        shopEntity.setPlatForm(IEnumConvert.valueOf(addShopParam.getPlatForm(), PlatFormEnum.class));

        shopEntity.setAuthorization(SuccessfulEnum.NO);
        shopEntity.setDataStatus(DataStatusEnum.ENABLE);
        shopEntity.setCreatedTime(LocalDateTime.now());
        shopEntity.setUpdateTime(LocalDateTime.now());
        return shopEntity;

    }

    private ShopEntity createPreShopInfoV2(AddShopParamV2 addShopParamV2, String userId) {
        String sysShopId = IdUtil.getSnowflake().nextIdStr();
        ShopEntity shopEntity = new ShopEntity();
        shopEntity.setUserId(userId);
        shopEntity.setSysShopId(sysShopId);
        shopEntity.setAccessToken(addShopParamV2.getAccessToken());
        shopEntity.setShopId(Long.valueOf(sysShopId));
        shopEntity.setShopName(addShopParamV2.getShopName());
        shopEntity.setUrl(addShopParamV2.getUrl());
        shopEntity.setLogoUrl(addShopParamV2.getLogoUrl());
        shopEntity.setPlatForm(IEnumConvert.valueOf(addShopParamV2.getPlatForm(), PlatFormEnum.class));

        shopEntity.setAuthorization(SuccessfulEnum.NO);
        shopEntity.setDataStatus(DataStatusEnum.ENABLE);
        shopEntity.setCreatedTime(LocalDateTime.now());
        shopEntity.setUpdateTime(LocalDateTime.now());
        return shopEntity;
    }
}
